Import Data

crowdfunding<-read.csv( "forqrm.csv" ,header=1)
head(crowdfunding)
library(lmtest)
Loading required package: zoo

Attaching package: 'zoo'

The following objects are masked from 'package:base':

    as.Date, as.Date.numeric
rownames(crowdfunding)<-crowdfunding$State

Find Topics

1.Geography information

  1. Geography information:found the significally different by state/by region
  • Amount
  • successfull rate within graphy/plot

2. Factors analysis:

  1. factors:studying the relationship between Successful Rate and other factors:
  • Higher Eduction:pAdDeg;
  • Ginicoeff
  • average_pledged_amount_of_Grand.Total

3. total regression

summary(lm(successful.rate2pAdDeg$residuals~crowdfunding$PovRate1))

Call:
lm(formula = successful.rate2pAdDeg$residuals ~ crowdfunding$PovRate1)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.197685 -0.048501 -0.000564  0.048829  0.163646 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)   
(Intercept)           -0.15641    0.05357  -2.920  0.00532 **
crowdfunding$PovRate1  1.05668    0.35451   2.981  0.00451 **
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.07615 on 48 degrees of freedom
Multiple R-squared:  0.1562,    Adjusted R-squared:  0.1386 
F-statistic: 8.884 on 1 and 48 DF,  p-value: 0.004505
summary(lm(successful.rate2pAdDeg$residuals~crowdfunding$GiniCoeff))

Call:
lm(formula = successful.rate2pAdDeg$residuals ~ crowdfunding$GiniCoeff)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.195484 -0.051186  0.004758  0.054168  0.147777 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)  
(Intercept)             -0.6411     0.2860  -2.242   0.0296 *
crowdfunding$GiniCoeff   1.4178     0.6319   2.244   0.0295 *
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.07887 on 48 degrees of freedom
Multiple R-squared:  0.09492,   Adjusted R-squared:  0.07606 
F-statistic: 5.034 on 1 and 48 DF,  p-value: 0.02951

Geography information

Geography information-barplot or lineplot

par(mfrow=c(1,2) )
#barplot(crowdfunding$count_of_Grand.Total,names.arg = crowdfunding$State,col="skyblue")
barplot(crowdfunding$count_of_Grand.Total,col="orange",axes = 0,xlab = "State",,ylab="Count of Projects",main="Count of Projects by States")
barplot(crowdfunding$successful.rate,col="skyblue",axes  = 0,xlab = "State",main="Successful Rate by States",ylab="Successful Rate")

Geography information-simpleplot

par(mfrow=c(1,2) )
#count_of_Grand.Total
plot(crowdfunding$count_of_Grand.Total,col=crowdfunding$Region, main="Count of Project  Plot",ylab="Successful Rate",xaxt="n",xlab="State")
#axis(side=1,at=c(1,2,3,4,5,6,7,8),labels=c(crowdfunding$State))
legend("center",legend = levels(crowdfunding$Region),cex = 0.8, pch = 1,col=1:3)
#successful.rate
plot(crowdfunding$successful.rate,col=crowdfunding$Region, main="Successful Rate Plot",ylab="Successful Rate",xaxt="n",xlab="State")
#axis(side=1,at=c(1,2,3,4,5,6,7,8),labels=c(crowdfunding$State))
legend("bottomleft",legend = levels(crowdfunding$Region),cex = 0.8, pch = 1,col=1:3)

Geography information-boxplot

par(mfrow=c(1,2))
#Boxplot for successful.rate and count_of_Grand.Total
#count_of_Grand.Total
boxplot(log(crowdfunding$count_of_Grand.Total[crowdfunding$Region=="Midwest"]),log(crowdfunding$count_of_Grand.Total[crowdfunding$Region=="Northeast"]),log(crowdfunding$count_of_Grand.Total[crowdfunding$Region=="South"]),log(crowdfunding$count_of_Grand.Total[crowdfunding$Region=="West"]),names=levels(crowdfunding$Region),main="Count of Projects BoxPlot by Region")
#successful.rate
boxplot(crowdfunding$successful.rate[crowdfunding$Region=="Midwest"],crowdfunding$successful.rate[crowdfunding$Region=="Northeast"],crowdfunding$successful.rate[crowdfunding$Region=="South"],crowdfunding$successful.rate[crowdfunding$Region=="West"],names=levels(crowdfunding$Region),main="Successful Rate BoxPlot by Region")

Geography information-t.test

#t.test(crowdfunding$successful.rate[crowdfunding$Region=="West"],crowdfunding$successful.rate[crowdfunding$Region=="Northeast"])
#t.test(crowdfunding$count_of_Grand.Total[crowdfunding$Region=="West"],crowdfunding$count_of_Grand.Total[crowdfunding$Region=="Northeast"])
#calcualte P Value in the t.test of Successful Rate by Region 
p=NULL
temp<-NULL
for (location1 in c(levels(crowdfunding$Region))){
  for (location2 in c(levels(crowdfunding$Region))){
    if (1){
      temp<-t.test(crowdfunding$successful.rate[crowdfunding$Region==location1],crowdfunding$successful.rate[crowdfunding$Region==location2])
      if(temp$p.value<=0.1){
        #print(c(location1,location2,temp$p.value))
      }
      p<-c(p,temp$p.value)}}}
SR.t.test.p.vlaue<-as.data.frame(matrix(p,4,4),row.names = c(levels(crowdfunding$Region)))
colnames(SR.t.test.p.vlaue)<-c(levels(crowdfunding$Region))
print("Successful Rate by Region")
[1] "Successful Rate by Region"
SR.t.test.p.vlaue
#--------------------------------------------------------
#calcualte P Value in the t.test of Count of projects by Region 
p=NULL
temp<-NULL
for (location1 in c(levels(crowdfunding$Region))){
  for (location2 in c(levels(crowdfunding$Region))){
    if (1){
      temp<-t.test(log(crowdfunding$count_of_Grand.Total[crowdfunding$Region==location1]),log(crowdfunding$count_of_Grand.Total[crowdfunding$Region==location2]))
      if(temp$p.value<=0.1){
        #print(c(location1,location2,temp$p.value))
      }
      p<-c(p,temp$p.value)}}}
CP.t.test.p.vlaue<-as.data.frame(matrix(p,4,4),row.names = c(levels(crowdfunding$Region)))
colnames(CP.t.test.p.vlaue)<-c(levels(crowdfunding$Region))
print("Count of Projects by Region ")
[1] "Count of Projects by Region "
CP.t.test.p.vlaue
#--------------------------------------------------------

Factors analysis

This article is to analyse the factors to the crowdfunding successful rate. I guess the Education, the inequity of family income and the poverty rate may be related to the crowdfunding successful rate. and in the follow context, i will analyse the those factors.

Firstly, The Statistical Summary ### Factors Analysis-Statistical Summary

library(moments)
summary(crowdfunding$successful.rate)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.1250  0.3179  0.3636  0.3631  0.4095  0.5484 
kurtosis(crowdfunding$successful.rate)
[1] 3.630147
summary(crowdfunding$GiniCoeff)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.4190  0.4400  0.4530  0.4522  0.4658  0.4990 
kurtosis(crowdfunding$GiniCoeff)
[1] 2.552647
summary(crowdfunding$pAdDeg)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
0.06100 0.07950 0.09200 0.09794 0.11000 0.16400 
kurtosis(crowdfunding$pAdDeg)
[1] 3.382781
summary(crowdfunding$PovRate1)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0920  0.1212  0.1480  0.1480  0.1705  0.2190 
kurtosis(crowdfunding$PovRate1)
[1] 2.159154

Factors Analysis-Plot for Factors

boxplot(crowdfunding$successful.rate,crowdfunding$GiniCoeff,crowdfunding$pAdDeg,crowdfunding$PovRate1,names = c("Successful Rate","GiniCoeff","Higher Education","PovRate1"),main="Factors Box Plot")
par(mfrow=c(2,2))

plot(crowdfunding$successful.rate,col="red",pch=10,xlab="State",ylab="Successful Rate",xaxt="n",main="Successful Rate Plot")
plot(crowdfunding$GiniCoeff,col="green",pch=18,xlab="State",xaxt="n",ylab="GiniCoeff ",xaxt="n",main="GiniCoeff Plot")
plot(crowdfunding$pAdDeg,col="blue",pch=15,xlab="State",xaxt="n",ylab="Adanced Education Rate",xaxt="n",main="Adanced Education Rate Plot")
plot(crowdfunding$PovRate1,col="black",pch=16,xlab="State",xaxt="n",ylab="Poverty Rate",xaxt="n",main="Poverty Rate Plot")

hc<-hclust(dist(crowdfunding),method = "ward.D", members = NULL)
NAs introduced by coercion
plclust(hc)
'plclust' is deprecated.
Use 'plot' instead.
See help("Deprecated")
rect.hclust(hc,k=3)

heatmap(as.matrix(dist(crowdfunding,method= 'euclidean')),labRow = F, labCol = F)
NAs introduced by coercion

result<-cutree(hc,k=3)
as.data.frame(result)
pie(result)

barplot(result,col = "blue")

#table(result)
#summary(result)
plot(result,type = "p")

library(ggplot2)
mds2 <- -cmdscale(dist(crowdfunding))
NAs introduced by coercion
plot(mds2, type="n", axes=FALSE, ann=FALSE)
text(mds2, labels=rownames(mds2), xpd = NA)

mds<-cmdscale(dist(crowdfunding),k=3,eig=T)
NAs introduced by coercion
x = mds$points[,1]
y = mds$points[,2]
p=ggplot(data.frame(x,y),aes(x,y))
p+geom_point(size=5 , alpha=0.8 , aes(colour=factor(result) ))

k2<-kmeans(all,centers=5,nstart=10)
summary(k2)
             Length Class  Mode   
cluster       49    -none- numeric
centers      225    -none- numeric
totss          1    -none- numeric
withinss       5    -none- numeric
tot.withinss   1    -none- numeric
betweenss      1    -none- numeric
size           5    -none- numeric
iter           1    -none- numeric
ifault         1    -none- numeric
library(car)
scatterplot(crowdfunding$successful.rate,log(crowdfunding$average_of_goal_Grand.Total),pch=19)

scatterplot(crowdfunding$successful.rate~crowdfunding$GiniCoeff,pch=19)

scatterplot(crowdfunding$successful.rate~crowdfunding$PovRate1,pch=19)

scatterplot(crowdfunding$successful.rate~crowdfunding$Densitym2,pch=19)

scatterplot(crowdfunding$successful.rate~crowdfunding$pHigh,pch=19)

scatterplot(crowdfunding$successful.rate~crowdfunding$pBatDeg,pch=19)

scatterplot(crowdfunding$successful.rate~crowdfunding$pAdDeg,pch=19)

Factors Analysis-Successful Rate|PovRate1

#redo scatterplot with Successful Rate-PovRate1
scatterplot(crowdfunding$successful.rate,crowdfunding$PovRate1,pch=19)

anova(successful.rate2PovRate1)
Analysis of Variance Table

Response: crowdfunding$successful.rate
                      Df  Sum Sq   Mean Sq F value Pr(>F)
crowdfunding$PovRate1  1 0.01157 0.0115683  1.4698 0.2313
Residuals             48 0.37780 0.0078708               
ggplot(crowdfunding,aes(x=PovRate1,y=successful.rate,main = "Successful rate~PovRate"))+geom_point(aes(col=Region))+geom_smooth(method = "loess")
par(mfrow=c(1,2))

boxplot(crowdfunding$successful.rate,crowdfunding$PovRate1,names=c("Successful Rate","PovRate1"))
boxplot(crowdfunding$successful.rate[crowdfunding$PovRate1>mean(crowdfunding$PovRate1)],crowdfunding$successful.rate[crowdfunding$PovRate1<=mean(crowdfunding$PovRate1)],col = c("green","deepskyblue"),names=c("Successful%(High PovRate)","Successful%(Low PovRate)"),xlab="Successful rate by PovRate1")

t.test(crowdfunding$successful.rate[crowdfunding$PovRate1>mean(crowdfunding$PovRate1)],crowdfunding$successful.rate[crowdfunding$PovRate1<=mean(crowdfunding$PovRate1)])

    Welch Two Sample t-test

data:  crowdfunding$successful.rate[crowdfunding$PovRate1 > mean(crowdfunding$PovRate1)] and crowdfunding$successful.rate[crowdfunding$PovRate1 <= mean(crowdfunding$PovRate1)]
t = -0.01904, df = 43.704, p-value = 0.9849
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.05105839  0.05010288
sample estimates:
mean of x mean of y 
0.3628157 0.3632935 
plot(crowdfunding$successful.rate,crowdfunding$PovRate1,pch=19,col=crowdfunding$Region,xlab="Successful Rate",ylab="PovRate1",main="Successful Rate-PovRate1 Plot with lowess line")
points(lowess(crowdfunding$successful.rate,crowdfunding$PovRate1,f=1/3),pch=4,col="orange",type="l")
#abline(lm(crowdfunding$successful.rate~crowdfunding$PovRate1),col="orange")
legend("topleft",legend = levels(crowdfunding$Region),cex = 0.8, pch = 19,col=1:3)
qqplot(crowdfunding$successful.rate,crowdfunding$PovRate1,pch=1,col=crowdfunding$Region,main="QQ plot: (Successful Rate & PovRate)")
qqline(crowdfunding$successful.rate,crowdfunding$PovRate1,col="red")
the condition has length > 1 and only the first element will be used
legend("topleft",legend = levels(crowdfunding$Region), pch = 19,col=1:3)
par(mfrow=c(1,1))

#qqnorm(crowdfunding$successful.rate,col=crowdfunding$Region,xlab="Successful Rate")
#qqline(crowdfunding$successful.rate,col="red")
qqnorm(crowdfunding$PovRate1,col=crowdfunding$Region,pch=18,xlab ="PovRate1")
qqline(crowdfunding$PovRate1,col="red")

Factors Analysis-Successful Rate|GiniCoeff

ggplot(crowdfunding,aes(x=GiniCoeff,y=successful.rate,main = "Successful rate~GiniCoeff"))+geom_point(aes(col=Region))+geom_smooth(method = "loess")
anova(successful.rate2GiniCoeff)
Analysis of Variance Table

Response: crowdfunding$successful.rate
                       Df  Sum Sq  Mean Sq F value   Pr(>F)   
crowdfunding$GiniCoeff  1 0.06236 0.062361  9.1537 0.003981 **
Residuals              48 0.32701 0.006813                    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
par(mfrow=c(1,2))

boxplot(crowdfunding$successful.rate,crowdfunding$GiniCoeff,names=c("Successful rate","GiniCoeff"))
boxplot(crowdfunding$successful.rate[crowdfunding$GiniCoeff>mean(crowdfunding$GiniCoeff)],crowdfunding$successful.rate[crowdfunding$GiniCoeff<=mean(crowdfunding$GiniCoeff)],col = c("darkorchid2","dodgerblue"),names=c("Successful%(High GiniCoeff)","Successful%(Low GiniCoeff)"),xlab="Successful rate by GiniCoeff")

t.test(crowdfunding$successful.rate[crowdfunding$GiniCoeff>mean(crowdfunding$GiniCoeff)],crowdfunding$successful.rate[crowdfunding$GiniCoeff<=mean(crowdfunding$GiniCoeff)])

    Welch Two Sample t-test

data:  crowdfunding$successful.rate[crowdfunding$GiniCoeff > mean(crowdfunding$GiniCoeff)] and crowdfunding$successful.rate[crowdfunding$GiniCoeff <= mean(crowdfunding$GiniCoeff)]
t = 1.6383, df = 43.111, p-value = 0.1086
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.009375926  0.090607105
sample estimates:
mean of x mean of y 
0.3833720 0.3427564 
plot(crowdfunding$successful.rate,crowdfunding$GiniCoeff,f=1/3 ,pch=19,col="blue",xlab="Successful Rate",ylab="GiniCoeff",main="Successful Rate-GiniCoeff Plot with lowess line")
points(lowess(crowdfunding$successful.rate,crowdfunding$GiniCoeff,f=1/3),pch=4,col="red",type="l")
qqplot(crowdfunding$successful.rate,crowdfunding$GiniCoeff,pch=19,col="red",main="Q-Q Plot: Successful Rate-GiniCoeff")
qqline(crowdfunding$successful.rate,crowdfunding$GiniCoeff)
the condition has length > 1 and only the first element will be used
#qqnorm(crowdfunding$successful.rate,col="orange",xlab="Successful Rate")
#qqline(crowdfunding$successful.rate,col="red")
par(mfrow=c(1,1))

qqnorm(crowdfunding$GiniCoeff,col="blue",pch=20,xlab="GiniCoeff")
qqline(crowdfunding$GiniCoeff,col="red")

Factors Analysis-Successful Rate|Adanced Education

ggplot(crowdfunding,aes(x=pAdDeg,y=successful.rate,main = "Successful rate~GiniCoeff"))+geom_point(aes(col=Region))+geom_smooth(method = "loess")
anova(successful.rate2pAdDeg)
Analysis of Variance Table

Response: crowdfunding$successful.rate
                    Df  Sum Sq  Mean Sq F value   Pr(>F)   
crowdfunding$pAdDeg  1 0.05947 0.059469  8.6527 0.005015 **
Residuals           48 0.32990 0.006873                    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
par(mfrow=c(1,2))

boxplot(crowdfunding$successful.rate,crowdfunding$pAdDeg,names=c("Successful rate","Adanced Education"))
boxplot(crowdfunding$successful.rate[crowdfunding$pAdDeg>mean(crowdfunding$pAdDeg)],crowdfunding$successful.rate[crowdfunding$pAdDeg<=mean(crowdfunding$pAdDeg)],col = c("darkorchid2","dodgerblue"),names=c("Successful%(High Adanced Education)","Successful%(Low Adanced Education)"),xlab="Successful rate by Adanced Education")

t.test(crowdfunding$successful.rate[crowdfunding$pAdDeg>mean(crowdfunding$pAdDeg)],crowdfunding$successful.rate[crowdfunding$pAdDeg<=mean(crowdfunding$pAdDeg)])

    Welch Two Sample t-test

data:  crowdfunding$successful.rate[crowdfunding$pAdDeg > mean(crowdfunding$pAdDeg)] and crowdfunding$successful.rate[crowdfunding$pAdDeg <= mean(crowdfunding$pAdDeg)]
t = 3.5483, df = 45.573, p-value = 0.0009119
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.03480093 0.12610121
sample estimates:
mean of x mean of y 
0.4097258 0.3292747 
plot(crowdfunding$successful.rate,crowdfunding$pAdDeg,f=1/3 ,pch=19,col="blue",xlab="Successful Rate",ylab="Adanced Education",main="Successful Rate-Adanced Education Plot with lowess line")
points(lowess(crowdfunding$successful.rate,crowdfunding$pAdDeg,f=1/3),pch=4,col="red",type="l")
qqplot(crowdfunding$successful.rate,crowdfunding$pAdDeg,pch=19,col="red",main="Q-Q Plot: Successful Rate-Adanced Education")
qqline(crowdfunding$successful.rate,crowdfunding$pAdDeg)
the condition has length > 1 and only the first element will be used
#qqnorm(crowdfunding$successful.rate,col="orange",xlab="Successful Rate")
#qqline(crowdfunding$successful.rate,col="red")
par(mfrow=c(1,1))

qqnorm(crowdfunding$pAdDeg,col="blue",pch=20,xlab="Adanced Education")
qqline(crowdfunding$pAdDeg,col="red")

LS0tCnRpdGxlOiAiQXNzaWdubWVudCIKYXV0aG9yOiAic24wd2ZyZWUiCmRhdGU6ICIxMi8xNi8yMDE2IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKLS0tCgoKIyMgSW1wb3J0IERhdGEKYGBge3IgaW1wb3J0IGRhdGV9CmNyb3dkZnVuZGluZzwtcmVhZC5jc3YoICJmb3Jxcm0uY3N2IiAsaGVhZGVyPTEpCmhlYWQoY3Jvd2RmdW5kaW5nKQpsaWJyYXJ5KGxtdGVzdCkKcm93bmFtZXMoY3Jvd2RmdW5kaW5nKTwtY3Jvd2RmdW5kaW5nJFN0YXRlCmBgYAoKIyMgRmluZCBUb3BpY3MKIyMjIDEuR2VvZ3JhcGh5IGluZm9ybWF0aW9uCgoxLiBHZW9ncmFwaHkgaW5mb3JtYXRpb246Zm91bmQgdGhlIHNpZ25pZmljYWxseSBkaWZmZXJlbnQgYnkgc3RhdGUvYnkgcmVnaW9uCiAgKyBBbW91bnQKICArIHN1Y2Nlc3NmdWxsIHJhdGUKICB3aXRoaW4gZ3JhcGh5L3Bsb3QKICAKIyMjIDIuIEZhY3RvcnMgYW5hbHlzaXM6CiAgCjIuIGZhY3RvcnM6c3R1ZHlpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIFN1Y2Nlc3NmdWwgUmF0ZSBhbmQgb3RoZXIgZmFjdG9yczoKICArIEhpZ2hlciBFZHVjdGlvbjpwQWREZWc7CiAgKyBHaW5pY29lZmYKICArIGF2ZXJhZ2VfcGxlZGdlZF9hbW91bnRfb2ZfR3JhbmQuVG90YWwKCgojIyMgMy4gdG90YWwgcmVncmVzc2lvbgpgYGB7ciByZWdyZXNzaW9ufQoKc3VjY2Vzc2Z1bC5yYXRlMkdpbmlDb2VmZjwtbG0oY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZX5jcm93ZGZ1bmRpbmckR2luaUNvZWZmKSNzaWduaWZpY2FudDowLjAwMzk4CnN1bW1hcnkoc3VjY2Vzc2Z1bC5yYXRlMkdpbmlDb2VmZikKCnN1Y2Nlc3NmdWwucmF0ZTJQb3ZSYXRlMTwtbG0oY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZX5jcm93ZGZ1bmRpbmckUG92UmF0ZTEpIzAuMjMxCnN1bW1hcnkoc3VjY2Vzc2Z1bC5yYXRlMlBvdlJhdGUxKQoKc3VtbWFyeShsbShjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlfmNyb3dkZnVuZGluZyRwSGlnaCkpI2JhZDowLjIzMjAgCnN1bW1hcnkobG0oY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZX5jcm93ZGZ1bmRpbmckcEJhdERlZykpI2xvdzowLjA1NTExCgpzdWNjZXNzZnVsLnJhdGUycEFkRGVnPC1sbShjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlfmNyb3dkZnVuZGluZyRwQWREZWcpI3NpZ25pZmljYW50OjAuMDA1MDEKc3VtbWFyeShzdWNjZXNzZnVsLnJhdGUycEFkRGVnKQoKI3N1cHBsZW1lbnQgcmVncmVzc2lvbgpzdW1tYXJ5KGxtKGNyb3dkZnVuZGluZyRHaW5pQ29lZmZ+Y3Jvd2RmdW5kaW5nJHBBZERlZykpI3NpZ25pZmljYW50OjAuMDM1MwoKc3VtbWFyeShsbShzdWNjZXNzZnVsLnJhdGUyUG92UmF0ZTEkcmVzaWR1YWxzfmNyb3dkZnVuZGluZyRwQWREZWcpKSMwLjAwMDM4ODEKc3VtbWFyeShsbShzdWNjZXNzZnVsLnJhdGUyUG92UmF0ZTEkcmVzaWR1YWxzfmNyb3dkZnVuZGluZyRHaW5pQ29lZmYpKSMwLjAyNjQKCnN1bW1hcnkobG0oc3VjY2Vzc2Z1bC5yYXRlMkdpbmlDb2VmZiRyZXNpZHVhbHN+Y3Jvd2RmdW5kaW5nJHBBZERlZykpI3Jlc2lkdWFscyB+IEFEZGVnOjAuMDM2OApzdW1tYXJ5KGxtKHN1Y2Nlc3NmdWwucmF0ZTJHaW5pQ29lZmYkcmVzaWR1YWxzfmNyb3dkZnVuZGluZyRQb3ZSYXRlMSkpI3Jlc2lkdWFscyB+IFBvdlJhdGUxOjAuNzcxCgpzdW1tYXJ5KGxtKHN1Y2Nlc3NmdWwucmF0ZTJwQWREZWckcmVzaWR1YWxzfmNyb3dkZnVuZGluZyRQb3ZSYXRlMSkpIzAuMDA0NTA1CnN1bW1hcnkobG0oc3VjY2Vzc2Z1bC5yYXRlMnBBZERlZyRyZXNpZHVhbHN+Y3Jvd2RmdW5kaW5nJEdpbmlDb2VmZikpIzAuMDI5NQoKCiNzdW1tYXJ5KGxtKGxvZyhjcm93ZGZ1bmRpbmckYXZlcmFnZV9wbGVkZ2VkX2Ftb3VudF9vZl9HcmFuZC5Ub3RhbCl+Y3Jvd2RmdW5kaW5nJEdpbmlDb2VmZikpIzAuMDIzNTcKCgpgYGAKCiMjIEdlb2dyYXBoeSBpbmZvcm1hdGlvbgoKCiMjIyBHZW9ncmFwaHkgaW5mb3JtYXRpb24tYmFycGxvdCBvciBsaW5lcGxvdApgYGB7ciBHZW9ncmFwaHkgaW5mb3JtYXRpb24tYmFycGxvdC9saW5lcGxvdH0KcGFyKG1mcm93PWMoMSwyKSApCiNiYXJwbG90KGNyb3dkZnVuZGluZyRjb3VudF9vZl9HcmFuZC5Ub3RhbCxuYW1lcy5hcmcgPSBjcm93ZGZ1bmRpbmckU3RhdGUsY29sPSJza3libHVlIikKYmFycGxvdChjcm93ZGZ1bmRpbmckY291bnRfb2ZfR3JhbmQuVG90YWwsY29sPSJvcmFuZ2UiLGF4ZXMgPSAwLHhsYWIgPSAiU3RhdGUiLCx5bGFiPSJDb3VudCBvZiBQcm9qZWN0cyIsbWFpbj0iQ291bnQgb2YgUHJvamVjdHMgYnkgU3RhdGVzIikKYmFycGxvdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlLGNvbD0ic2t5Ymx1ZSIsYXhlcyAgPSAwLHhsYWIgPSAiU3RhdGUiLG1haW49IlN1Y2Nlc3NmdWwgUmF0ZSBieSBTdGF0ZXMiLHlsYWI9IlN1Y2Nlc3NmdWwgUmF0ZSIpCmBgYAoKCiMjIyBHZW9ncmFwaHkgaW5mb3JtYXRpb24tc2ltcGxlcGxvdApgYGB7ciBHZW9ncmFwaHkgaW5mb3JtYXRpb24tc2ltcGxlcGxvdH0KcGFyKG1mcm93PWMoMSwyKSApCgojY291bnRfb2ZfR3JhbmQuVG90YWwKcGxvdChjcm93ZGZ1bmRpbmckY291bnRfb2ZfR3JhbmQuVG90YWwsY29sPWNyb3dkZnVuZGluZyRSZWdpb24sIG1haW49IkNvdW50IG9mIFByb2plY3QgIFBsb3QiLHlsYWI9IlN1Y2Nlc3NmdWwgUmF0ZSIseGF4dD0ibiIseGxhYj0iU3RhdGUiKQojYXhpcyhzaWRlPTEsYXQ9YygxLDIsMyw0LDUsNiw3LDgpLGxhYmVscz1jKGNyb3dkZnVuZGluZyRTdGF0ZSkpCmxlZ2VuZCgiY2VudGVyIixsZWdlbmQgPSBsZXZlbHMoY3Jvd2RmdW5kaW5nJFJlZ2lvbiksY2V4ID0gMC44LCBwY2ggPSAxLGNvbD0xOjMpCgoKCiNzdWNjZXNzZnVsLnJhdGUKcGxvdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlLGNvbD1jcm93ZGZ1bmRpbmckUmVnaW9uLCBtYWluPSJTdWNjZXNzZnVsIFJhdGUgUGxvdCIseWxhYj0iU3VjY2Vzc2Z1bCBSYXRlIix4YXh0PSJuIix4bGFiPSJTdGF0ZSIpCiNheGlzKHNpZGU9MSxhdD1jKDEsMiwzLDQsNSw2LDcsOCksbGFiZWxzPWMoY3Jvd2RmdW5kaW5nJFN0YXRlKSkKbGVnZW5kKCJib3R0b21sZWZ0IixsZWdlbmQgPSBsZXZlbHMoY3Jvd2RmdW5kaW5nJFJlZ2lvbiksY2V4ID0gMC44LCBwY2ggPSAxLGNvbD0xOjMpCmBgYAoKIyMjIEdlb2dyYXBoeSBpbmZvcm1hdGlvbi1ib3hwbG90CmBgYHtyIEdlb2dyYXBoeSBpbmZvcm1hdGlvbi1ib3hwbG90fQpwYXIobWZyb3c9YygxLDIpKQojQm94cGxvdCBmb3Igc3VjY2Vzc2Z1bC5yYXRlIGFuZCBjb3VudF9vZl9HcmFuZC5Ub3RhbAojY291bnRfb2ZfR3JhbmQuVG90YWwKYm94cGxvdChsb2coY3Jvd2RmdW5kaW5nJGNvdW50X29mX0dyYW5kLlRvdGFsW2Nyb3dkZnVuZGluZyRSZWdpb249PSJNaWR3ZXN0Il0pLGxvZyhjcm93ZGZ1bmRpbmckY291bnRfb2ZfR3JhbmQuVG90YWxbY3Jvd2RmdW5kaW5nJFJlZ2lvbj09Ik5vcnRoZWFzdCJdKSxsb2coY3Jvd2RmdW5kaW5nJGNvdW50X29mX0dyYW5kLlRvdGFsW2Nyb3dkZnVuZGluZyRSZWdpb249PSJTb3V0aCJdKSxsb2coY3Jvd2RmdW5kaW5nJGNvdW50X29mX0dyYW5kLlRvdGFsW2Nyb3dkZnVuZGluZyRSZWdpb249PSJXZXN0Il0pLG5hbWVzPWxldmVscyhjcm93ZGZ1bmRpbmckUmVnaW9uKSxtYWluPSJDb3VudCBvZiBQcm9qZWN0cyBCb3hQbG90IGJ5IFJlZ2lvbiIpCgojc3VjY2Vzc2Z1bC5yYXRlCmJveHBsb3QoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZVtjcm93ZGZ1bmRpbmckUmVnaW9uPT0iTWlkd2VzdCJdLGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGVbY3Jvd2RmdW5kaW5nJFJlZ2lvbj09Ik5vcnRoZWFzdCJdLGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGVbY3Jvd2RmdW5kaW5nJFJlZ2lvbj09IlNvdXRoIl0sY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZVtjcm93ZGZ1bmRpbmckUmVnaW9uPT0iV2VzdCJdLG5hbWVzPWxldmVscyhjcm93ZGZ1bmRpbmckUmVnaW9uKSxtYWluPSJTdWNjZXNzZnVsIFJhdGUgQm94UGxvdCBieSBSZWdpb24iKQpgYGAKCgojIyMgR2VvZ3JhcGh5IGluZm9ybWF0aW9uLXQudGVzdApgYGB7ciBHZW9ncmFwaHkgaW5mb3JtYXRpb24tdC50ZXN0fQojdC50ZXN0KGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGVbY3Jvd2RmdW5kaW5nJFJlZ2lvbj09Ildlc3QiXSxjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlW2Nyb3dkZnVuZGluZyRSZWdpb249PSJOb3J0aGVhc3QiXSkKI3QudGVzdChjcm93ZGZ1bmRpbmckY291bnRfb2ZfR3JhbmQuVG90YWxbY3Jvd2RmdW5kaW5nJFJlZ2lvbj09Ildlc3QiXSxjcm93ZGZ1bmRpbmckY291bnRfb2ZfR3JhbmQuVG90YWxbY3Jvd2RmdW5kaW5nJFJlZ2lvbj09Ik5vcnRoZWFzdCJdKQoKCiNjYWxjdWFsdGUgUCBWYWx1ZSBpbiB0aGUgdC50ZXN0IG9mIFN1Y2Nlc3NmdWwgUmF0ZSBieSBSZWdpb24gCgpwPU5VTEwKdGVtcDwtTlVMTApmb3IgKGxvY2F0aW9uMSBpbiBjKGxldmVscyhjcm93ZGZ1bmRpbmckUmVnaW9uKSkpewogIGZvciAobG9jYXRpb24yIGluIGMobGV2ZWxzKGNyb3dkZnVuZGluZyRSZWdpb24pKSl7CiAgICBpZiAoMSl7CiAgICAgIHRlbXA8LXQudGVzdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlW2Nyb3dkZnVuZGluZyRSZWdpb249PWxvY2F0aW9uMV0sY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZVtjcm93ZGZ1bmRpbmckUmVnaW9uPT1sb2NhdGlvbjJdKQogICAgICBpZih0ZW1wJHAudmFsdWU8PTAuMSl7CiAgICAgICAgI3ByaW50KGMobG9jYXRpb24xLGxvY2F0aW9uMix0ZW1wJHAudmFsdWUpKQogICAgICB9CiAgICAgIHA8LWMocCx0ZW1wJHAudmFsdWUpfX19ClNSLnQudGVzdC5wLnZsYXVlPC1hcy5kYXRhLmZyYW1lKG1hdHJpeChwLDQsNCkscm93Lm5hbWVzID0gYyhsZXZlbHMoY3Jvd2RmdW5kaW5nJFJlZ2lvbikpKQpjb2xuYW1lcyhTUi50LnRlc3QucC52bGF1ZSk8LWMobGV2ZWxzKGNyb3dkZnVuZGluZyRSZWdpb24pKQpwcmludCgiU3VjY2Vzc2Z1bCBSYXRlIGJ5IFJlZ2lvbiIpClNSLnQudGVzdC5wLnZsYXVlCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojY2FsY3VhbHRlIFAgVmFsdWUgaW4gdGhlIHQudGVzdCBvZiBDb3VudCBvZiBwcm9qZWN0cyBieSBSZWdpb24gCgpwPU5VTEwKdGVtcDwtTlVMTApmb3IgKGxvY2F0aW9uMSBpbiBjKGxldmVscyhjcm93ZGZ1bmRpbmckUmVnaW9uKSkpewogIGZvciAobG9jYXRpb24yIGluIGMobGV2ZWxzKGNyb3dkZnVuZGluZyRSZWdpb24pKSl7CiAgICBpZiAoMSl7CiAgICAgIHRlbXA8LXQudGVzdChsb2coY3Jvd2RmdW5kaW5nJGNvdW50X29mX0dyYW5kLlRvdGFsW2Nyb3dkZnVuZGluZyRSZWdpb249PWxvY2F0aW9uMV0pLGxvZyhjcm93ZGZ1bmRpbmckY291bnRfb2ZfR3JhbmQuVG90YWxbY3Jvd2RmdW5kaW5nJFJlZ2lvbj09bG9jYXRpb24yXSkpCiAgICAgIGlmKHRlbXAkcC52YWx1ZTw9MC4xKXsKICAgICAgICAjcHJpbnQoYyhsb2NhdGlvbjEsbG9jYXRpb24yLHRlbXAkcC52YWx1ZSkpCiAgICAgIH0KICAgICAgcDwtYyhwLHRlbXAkcC52YWx1ZSl9fX0KQ1AudC50ZXN0LnAudmxhdWU8LWFzLmRhdGEuZnJhbWUobWF0cml4KHAsNCw0KSxyb3cubmFtZXMgPSBjKGxldmVscyhjcm93ZGZ1bmRpbmckUmVnaW9uKSkpCmNvbG5hbWVzKENQLnQudGVzdC5wLnZsYXVlKTwtYyhsZXZlbHMoY3Jvd2RmdW5kaW5nJFJlZ2lvbikpCnByaW50KCJDb3VudCBvZiBQcm9qZWN0cyBieSBSZWdpb24gIikKQ1AudC50ZXN0LnAudmxhdWUKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgoKCmBgYAoKIyMgRmFjdG9ycyBhbmFseXNpcwpUaGlzIGFydGljbGUgaXMgdG8gYW5hbHlzZSB0aGUgZmFjdG9ycyB0byB0aGUgY3Jvd2RmdW5kaW5nIHN1Y2Nlc3NmdWwgcmF0ZS4KSSBndWVzcyB0aGUgRWR1Y2F0aW9uLCB0aGUgaW5lcXVpdHkgb2YgZmFtaWx5IGluY29tZSBhbmQgdGhlIHBvdmVydHkgcmF0ZSBtYXkgYmUgcmVsYXRlZCB0byB0aGUgY3Jvd2RmdW5kaW5nIHN1Y2Nlc3NmdWwgcmF0ZS4gYW5kIGluIHRoZSBmb2xsb3cgY29udGV4dCwgaSB3aWxsIGFuYWx5c2UgdGhlIHRob3NlIGZhY3RvcnMuCgpGaXJzdGx5LCBUaGUgU3RhdGlzdGljYWwgU3VtbWFyeQojIyMgRmFjdG9ycyBBbmFseXNpcy1TdGF0aXN0aWNhbCBTdW1tYXJ5CmBgYHtyIEZhY3RvcnMgQW5hbHlzaXMtU3RhdGlzdGljYWwgU3VtbWFyeX0KbGlicmFyeShtb21lbnRzKQoKc3VtbWFyeShjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlKQprdXJ0b3Npcyhjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlKQoKc3VtbWFyeShjcm93ZGZ1bmRpbmckR2luaUNvZWZmKQprdXJ0b3Npcyhjcm93ZGZ1bmRpbmckR2luaUNvZWZmKQoKc3VtbWFyeShjcm93ZGZ1bmRpbmckcEFkRGVnKQprdXJ0b3Npcyhjcm93ZGZ1bmRpbmckcEFkRGVnKQoKc3VtbWFyeShjcm93ZGZ1bmRpbmckUG92UmF0ZTEpCmt1cnRvc2lzKGNyb3dkZnVuZGluZyRQb3ZSYXRlMSkKCmBgYAoKIyMjIEZhY3RvcnMgQW5hbHlzaXMtUGxvdCBmb3IgRmFjdG9ycwpgYGB7ciBQbG90IGZvciBGYWN0b3JzfQoKYm94cGxvdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlLGNyb3dkZnVuZGluZyRHaW5pQ29lZmYsY3Jvd2RmdW5kaW5nJHBBZERlZyxjcm93ZGZ1bmRpbmckUG92UmF0ZTEsbmFtZXMgPSBjKCJTdWNjZXNzZnVsIFJhdGUiLCJHaW5pQ29lZmYiLCJIaWdoZXIgRWR1Y2F0aW9uIiwiUG92UmF0ZTEiKSxtYWluPSJGYWN0b3JzIEJveCBQbG90IikKCnBhcihtZnJvdz1jKDIsMikpCnBsb3QoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjb2w9InJlZCIscGNoPTEwLHhsYWI9IlN0YXRlIix5bGFiPSJTdWNjZXNzZnVsIFJhdGUiLHhheHQ9Im4iLG1haW49IlN1Y2Nlc3NmdWwgUmF0ZSBQbG90IikKcGxvdChjcm93ZGZ1bmRpbmckR2luaUNvZWZmLGNvbD0iZ3JlZW4iLHBjaD0xOCx4bGFiPSJTdGF0ZSIseGF4dD0ibiIseWxhYj0iR2luaUNvZWZmICIseGF4dD0ibiIsbWFpbj0iR2luaUNvZWZmIFBsb3QiKQpwbG90KGNyb3dkZnVuZGluZyRwQWREZWcsY29sPSJibHVlIixwY2g9MTUseGxhYj0iU3RhdGUiLHhheHQ9Im4iLHlsYWI9IkFkYW5jZWQgRWR1Y2F0aW9uIFJhdGUiLHhheHQ9Im4iLG1haW49IkFkYW5jZWQgRWR1Y2F0aW9uIFJhdGUgUGxvdCIpCnBsb3QoY3Jvd2RmdW5kaW5nJFBvdlJhdGUxLGNvbD0iYmxhY2siLHBjaD0xNix4bGFiPSJTdGF0ZSIseGF4dD0ibiIseWxhYj0iUG92ZXJ0eSBSYXRlIix4YXh0PSJuIixtYWluPSJQb3ZlcnR5IFJhdGUgUGxvdCIpCgpgYGAKCgoKCmBgYHtyIGttZWFuc30KaGM8LWhjbHVzdChkaXN0KGNyb3dkZnVuZGluZyksbWV0aG9kID0gIndhcmQuRCIsIG1lbWJlcnMgPSBOVUxMKQpwbGNsdXN0KGhjKQpyZWN0LmhjbHVzdChoYyxrPTMpCgoKaGVhdG1hcChhcy5tYXRyaXgoZGlzdChjcm93ZGZ1bmRpbmcsbWV0aG9kPSAnZXVjbGlkZWFuJykpLGxhYlJvdyA9IEYsIGxhYkNvbCA9IEYpCnJlc3VsdDwtY3V0cmVlKGhjLGs9MykKYXMuZGF0YS5mcmFtZShyZXN1bHQpCnBpZShyZXN1bHQpCmJhcnBsb3QocmVzdWx0LGNvbCA9ICJibHVlIikKI3RhYmxlKHJlc3VsdCkKI3N1bW1hcnkocmVzdWx0KQpwbG90KHJlc3VsdCx0eXBlID0gInAiKQoKCmxpYnJhcnkoZ2dwbG90MikKbWRzMiA8LSAtY21kc2NhbGUoZGlzdChjcm93ZGZ1bmRpbmcpKQpwbG90KG1kczIsIHR5cGU9Im4iLCBheGVzPUZBTFNFLCBhbm49RkFMU0UpCnRleHQobWRzMiwgbGFiZWxzPXJvd25hbWVzKG1kczIpLCB4cGQgPSBOQSkKCm1kczwtY21kc2NhbGUoZGlzdChjcm93ZGZ1bmRpbmcpLGs9MyxlaWc9VCkKeCA9IG1kcyRwb2ludHNbLDFdCnkgPSBtZHMkcG9pbnRzWywyXQpwPWdncGxvdChkYXRhLmZyYW1lKHgseSksYWVzKHgseSkpCnArZ2VvbV9wb2ludChzaXplPTUgLCBhbHBoYT0wLjggLCBhZXMoY29sb3VyPWZhY3RvcihyZXN1bHQpICkpCmsyPC1rbWVhbnMoYWxsLGNlbnRlcnM9NSxuc3RhcnQ9MTApCnN1bW1hcnkoazIpCgpgYGAKCmBgYHtyIHNjYXR0ZXJwbG90fQpsaWJyYXJ5KGNhcikKc2NhdHRlcnBsb3QoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxsb2coY3Jvd2RmdW5kaW5nJGF2ZXJhZ2Vfb2ZfZ29hbF9HcmFuZC5Ub3RhbCkscGNoPTE5KQpzY2F0dGVycGxvdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlfmNyb3dkZnVuZGluZyRHaW5pQ29lZmYscGNoPTE5KQpzY2F0dGVycGxvdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlfmNyb3dkZnVuZGluZyRQb3ZSYXRlMSxwY2g9MTkpCnNjYXR0ZXJwbG90KGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGV+Y3Jvd2RmdW5kaW5nJERlbnNpdHltMixwY2g9MTkpCnNjYXR0ZXJwbG90KGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGV+Y3Jvd2RmdW5kaW5nJHBIaWdoLHBjaD0xOSkKc2NhdHRlcnBsb3QoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZX5jcm93ZGZ1bmRpbmckcEJhdERlZyxwY2g9MTkpCnNjYXR0ZXJwbG90KGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGV+Y3Jvd2RmdW5kaW5nJHBBZERlZyxwY2g9MTkpCgoKYGBgCgoKIyMjIEZhY3RvcnMgQW5hbHlzaXMtU3VjY2Vzc2Z1bCBSYXRlfFBvdlJhdGUxCmBgYHtyIFN1Y2Nlc3NmdWwgUmF0ZS1Qb3ZSYXRlMX0KI3JlZG8gc2NhdHRlcnBsb3Qgd2l0aCBTdWNjZXNzZnVsIFJhdGUtUG92UmF0ZTEKc2NhdHRlcnBsb3QoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjcm93ZGZ1bmRpbmckUG92UmF0ZTEscGNoPTE5KQoKYW5vdmEoc3VjY2Vzc2Z1bC5yYXRlMlBvdlJhdGUxKQoKZ2dwbG90KGNyb3dkZnVuZGluZyxhZXMoeD1Qb3ZSYXRlMSx5PXN1Y2Nlc3NmdWwucmF0ZSxtYWluID0gIlN1Y2Nlc3NmdWwgcmF0ZX5Qb3ZSYXRlIikpK2dlb21fcG9pbnQoYWVzKGNvbD1SZWdpb24pKStnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiKQoKcGFyKG1mcm93PWMoMSwyKSkKCmJveHBsb3QoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjcm93ZGZ1bmRpbmckUG92UmF0ZTEsbmFtZXM9YygiU3VjY2Vzc2Z1bCBSYXRlIiwiUG92UmF0ZTEiKSkKYm94cGxvdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlW2Nyb3dkZnVuZGluZyRQb3ZSYXRlMT5tZWFuKGNyb3dkZnVuZGluZyRQb3ZSYXRlMSldLGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGVbY3Jvd2RmdW5kaW5nJFBvdlJhdGUxPD1tZWFuKGNyb3dkZnVuZGluZyRQb3ZSYXRlMSldLGNvbCA9IGMoImdyZWVuIiwiZGVlcHNreWJsdWUiKSxuYW1lcz1jKCJTdWNjZXNzZnVsJShIaWdoIFBvdlJhdGUpIiwiU3VjY2Vzc2Z1bCUoTG93IFBvdlJhdGUpIikseGxhYj0iU3VjY2Vzc2Z1bCByYXRlIGJ5IFBvdlJhdGUxIikKCgoKdC50ZXN0KGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGVbY3Jvd2RmdW5kaW5nJFBvdlJhdGUxPm1lYW4oY3Jvd2RmdW5kaW5nJFBvdlJhdGUxKV0sY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZVtjcm93ZGZ1bmRpbmckUG92UmF0ZTE8PW1lYW4oY3Jvd2RmdW5kaW5nJFBvdlJhdGUxKV0pCgoKCnBsb3QoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjcm93ZGZ1bmRpbmckUG92UmF0ZTEscGNoPTE5LGNvbD1jcm93ZGZ1bmRpbmckUmVnaW9uLHhsYWI9IlN1Y2Nlc3NmdWwgUmF0ZSIseWxhYj0iUG92UmF0ZTEiLG1haW49IlN1Y2Nlc3NmdWwgUmF0ZS1Qb3ZSYXRlMSBQbG90IHdpdGggbG93ZXNzIGxpbmUiKQpwb2ludHMobG93ZXNzKGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGUsY3Jvd2RmdW5kaW5nJFBvdlJhdGUxLGY9MS8zKSxwY2g9NCxjb2w9Im9yYW5nZSIsdHlwZT0ibCIpCiNhYmxpbmUobG0oY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZX5jcm93ZGZ1bmRpbmckUG92UmF0ZTEpLGNvbD0ib3JhbmdlIikKbGVnZW5kKCJ0b3BsZWZ0IixsZWdlbmQgPSBsZXZlbHMoY3Jvd2RmdW5kaW5nJFJlZ2lvbiksY2V4ID0gMC44LCBwY2ggPSAxOSxjb2w9MTozKQoKCnFxcGxvdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlLGNyb3dkZnVuZGluZyRQb3ZSYXRlMSxwY2g9MSxjb2w9Y3Jvd2RmdW5kaW5nJFJlZ2lvbixtYWluPSJRUSBwbG90OiAoU3VjY2Vzc2Z1bCBSYXRlICYgUG92UmF0ZSkiKQpxcWxpbmUoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjcm93ZGZ1bmRpbmckUG92UmF0ZTEsY29sPSJyZWQiKQpsZWdlbmQoInRvcGxlZnQiLGxlZ2VuZCA9IGxldmVscyhjcm93ZGZ1bmRpbmckUmVnaW9uKSwgcGNoID0gMTksY29sPTE6MykKCgoKCnBhcihtZnJvdz1jKDEsMSkpCiNxcW5vcm0oY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjb2w9Y3Jvd2RmdW5kaW5nJFJlZ2lvbix4bGFiPSJTdWNjZXNzZnVsIFJhdGUiKQojcXFsaW5lKGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGUsY29sPSJyZWQiKQpxcW5vcm0oY3Jvd2RmdW5kaW5nJFBvdlJhdGUxLGNvbD1jcm93ZGZ1bmRpbmckUmVnaW9uLHBjaD0xOCx4bGFiID0iUG92UmF0ZTEiKQpxcWxpbmUoY3Jvd2RmdW5kaW5nJFBvdlJhdGUxLGNvbD0icmVkIikKYGBgCgoKCgoKIyMjIEZhY3RvcnMgQW5hbHlzaXMtU3VjY2Vzc2Z1bCBSYXRlfEdpbmlDb2VmZgpgYGB7ciBTdWNjZXNzZnVsIFJhdGUtR2luaUNvZWZmfQoKZ2dwbG90KGNyb3dkZnVuZGluZyxhZXMoeD1HaW5pQ29lZmYseT1zdWNjZXNzZnVsLnJhdGUsbWFpbiA9ICJTdWNjZXNzZnVsIHJhdGV+R2luaUNvZWZmIikpK2dlb21fcG9pbnQoYWVzKGNvbD1SZWdpb24pKStnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiKQoKYW5vdmEoc3VjY2Vzc2Z1bC5yYXRlMkdpbmlDb2VmZikKCgoKcGFyKG1mcm93PWMoMSwyKSkKCgpib3hwbG90KGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGUsY3Jvd2RmdW5kaW5nJEdpbmlDb2VmZixuYW1lcz1jKCJTdWNjZXNzZnVsIHJhdGUiLCJHaW5pQ29lZmYiKSkKYm94cGxvdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlW2Nyb3dkZnVuZGluZyRHaW5pQ29lZmY+bWVhbihjcm93ZGZ1bmRpbmckR2luaUNvZWZmKV0sY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZVtjcm93ZGZ1bmRpbmckR2luaUNvZWZmPD1tZWFuKGNyb3dkZnVuZGluZyRHaW5pQ29lZmYpXSxjb2wgPSBjKCJkYXJrb3JjaGlkMiIsImRvZGdlcmJsdWUiKSxuYW1lcz1jKCJTdWNjZXNzZnVsJShIaWdoIEdpbmlDb2VmZikiLCJTdWNjZXNzZnVsJShMb3cgR2luaUNvZWZmKSIpLHhsYWI9IlN1Y2Nlc3NmdWwgcmF0ZSBieSBHaW5pQ29lZmYiKQoKCgoKCnQudGVzdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlW2Nyb3dkZnVuZGluZyRHaW5pQ29lZmY+bWVhbihjcm93ZGZ1bmRpbmckR2luaUNvZWZmKV0sY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZVtjcm93ZGZ1bmRpbmckR2luaUNvZWZmPD1tZWFuKGNyb3dkZnVuZGluZyRHaW5pQ29lZmYpXSkKCgpwbG90KGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGUsY3Jvd2RmdW5kaW5nJEdpbmlDb2VmZixmPTEvMyAscGNoPTE5LGNvbD0iYmx1ZSIseGxhYj0iU3VjY2Vzc2Z1bCBSYXRlIix5bGFiPSJHaW5pQ29lZmYiLG1haW49IlN1Y2Nlc3NmdWwgUmF0ZS1HaW5pQ29lZmYgUGxvdCB3aXRoIGxvd2VzcyBsaW5lIikKcG9pbnRzKGxvd2Vzcyhjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlLGNyb3dkZnVuZGluZyRHaW5pQ29lZmYsZj0xLzMpLHBjaD00LGNvbD0icmVkIix0eXBlPSJsIikKCgpxcXBsb3QoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjcm93ZGZ1bmRpbmckR2luaUNvZWZmLHBjaD0xOSxjb2w9InJlZCIsbWFpbj0iUS1RIFBsb3Q6IFN1Y2Nlc3NmdWwgUmF0ZS1HaW5pQ29lZmYiKQpxcWxpbmUoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjcm93ZGZ1bmRpbmckR2luaUNvZWZmKQoKCiNxcW5vcm0oY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjb2w9Im9yYW5nZSIseGxhYj0iU3VjY2Vzc2Z1bCBSYXRlIikKI3FxbGluZShjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlLGNvbD0icmVkIikKcGFyKG1mcm93PWMoMSwxKSkKcXFub3JtKGNyb3dkZnVuZGluZyRHaW5pQ29lZmYsY29sPSJibHVlIixwY2g9MjAseGxhYj0iR2luaUNvZWZmIikKcXFsaW5lKGNyb3dkZnVuZGluZyRHaW5pQ29lZmYsY29sPSJyZWQiKQoKYGBgCgoKCiMjIyBGYWN0b3JzIEFuYWx5c2lzLVN1Y2Nlc3NmdWwgUmF0ZXxBZGFuY2VkIEVkdWNhdGlvbgpgYGB7ciBTdWNjZXNzZnVsIFJhdGUtQWRhbmNlZCBFZHVjYXRpb259CmdncGxvdChjcm93ZGZ1bmRpbmcsYWVzKHg9cEFkRGVnLHk9c3VjY2Vzc2Z1bC5yYXRlLG1haW4gPSAiU3VjY2Vzc2Z1bCByYXRlfkdpbmlDb2VmZiIpKStnZW9tX3BvaW50KGFlcyhjb2w9UmVnaW9uKSkrZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIikKCmFub3ZhKHN1Y2Nlc3NmdWwucmF0ZTJwQWREZWcpCgpwYXIobWZyb3c9YygxLDIpKQoKYm94cGxvdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlLGNyb3dkZnVuZGluZyRwQWREZWcsbmFtZXM9YygiU3VjY2Vzc2Z1bCByYXRlIiwiQWRhbmNlZCBFZHVjYXRpb24iKSkKYm94cGxvdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlW2Nyb3dkZnVuZGluZyRwQWREZWc+bWVhbihjcm93ZGZ1bmRpbmckcEFkRGVnKV0sY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZVtjcm93ZGZ1bmRpbmckcEFkRGVnPD1tZWFuKGNyb3dkZnVuZGluZyRwQWREZWcpXSxjb2wgPSBjKCJkYXJrb3JjaGlkMiIsImRvZGdlcmJsdWUiKSxuYW1lcz1jKCJTdWNjZXNzZnVsJShIaWdoIEFkYW5jZWQgRWR1Y2F0aW9uKSIsIlN1Y2Nlc3NmdWwlKExvdyBBZGFuY2VkIEVkdWNhdGlvbikiKSx4bGFiPSJTdWNjZXNzZnVsIHJhdGUgYnkgQWRhbmNlZCBFZHVjYXRpb24iKQoKCnQudGVzdChjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlW2Nyb3dkZnVuZGluZyRwQWREZWc+bWVhbihjcm93ZGZ1bmRpbmckcEFkRGVnKV0sY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZVtjcm93ZGZ1bmRpbmckcEFkRGVnPD1tZWFuKGNyb3dkZnVuZGluZyRwQWREZWcpXSkKCgpwbG90KGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGUsY3Jvd2RmdW5kaW5nJHBBZERlZyxmPTEvMyAscGNoPTE5LGNvbD0iYmx1ZSIseGxhYj0iU3VjY2Vzc2Z1bCBSYXRlIix5bGFiPSJBZGFuY2VkIEVkdWNhdGlvbiIsbWFpbj0iU3VjY2Vzc2Z1bCBSYXRlLUFkYW5jZWQgRWR1Y2F0aW9uIFBsb3Qgd2l0aCBsb3dlc3MgbGluZSIpCnBvaW50cyhsb3dlc3MoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjcm93ZGZ1bmRpbmckcEFkRGVnLGY9MS8zKSxwY2g9NCxjb2w9InJlZCIsdHlwZT0ibCIpCgoKcXFwbG90KGNyb3dkZnVuZGluZyRzdWNjZXNzZnVsLnJhdGUsY3Jvd2RmdW5kaW5nJHBBZERlZyxwY2g9MTksY29sPSJyZWQiLG1haW49IlEtUSBQbG90OiBTdWNjZXNzZnVsIFJhdGUtQWRhbmNlZCBFZHVjYXRpb24iKQpxcWxpbmUoY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjcm93ZGZ1bmRpbmckcEFkRGVnKQoKCiNxcW5vcm0oY3Jvd2RmdW5kaW5nJHN1Y2Nlc3NmdWwucmF0ZSxjb2w9Im9yYW5nZSIseGxhYj0iU3VjY2Vzc2Z1bCBSYXRlIikKI3FxbGluZShjcm93ZGZ1bmRpbmckc3VjY2Vzc2Z1bC5yYXRlLGNvbD0icmVkIikKcGFyKG1mcm93PWMoMSwxKSkKcXFub3JtKGNyb3dkZnVuZGluZyRwQWREZWcsY29sPSJibHVlIixwY2g9MjAseGxhYj0iQWRhbmNlZCBFZHVjYXRpb24iKQpxcWxpbmUoY3Jvd2RmdW5kaW5nJHBBZERlZyxjb2w9InJlZCIpCgpgYGAKCg==